package org.example.hw.controller;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.example.hw.dto.link.AddLinkDto;
import org.example.hw.dto.link.ViewLinkDto;
import org.example.hw.exception.MyException;
import org.example.hw.model.Link;
import org.example.hw.model.User;
import org.example.hw.service.LinkService;
import org.example.hw.util.mapping.LinkMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class LinkController {

	@Autowired
	private LinkService linkService;

	private static final Logger LOGGER = LogManager.getLogger(LinkController.class);

	@RequestMapping(value = "/create", method = RequestMethod.GET)
	private String handleLinkAddGet(Model model) {

		LOGGER.debug("Handle link add get method invoked...");

		model.addAttribute("addLinkDto", new AddLinkDto());

		LOGGER.debug("Sending to add link page...");

		return "create";
	}

	@RequestMapping(value = "/create", method = RequestMethod.POST)
	private String handleLinkAddPost(@Valid @ModelAttribute AddLinkDto addLinkDto, BindingResult result, Model model,
			HttpSession session) {

		LOGGER.debug("Handle link add post controller invoked...");

		if (result.hasErrors()) {
			LOGGER.info("Binding error.");

			return "create";
		}

		User createdBy = (User) session.getAttribute("user");

		Link link = LinkMapping.mapAdd(addLinkDto, createdBy);

		try {
			Link saved = linkService.save(link);

			if (createdBy == null) {
				return "redirect:/viewLink/anonymous/" + saved.getCustomUrl();
			} else {
				return "redirect:/viewLink/" + saved.getCustomUrl();
			}

		} catch (MyException e) {
			LOGGER.error("Exception occured, see following stack trace for more details.", e);
			// TODO: poruka na stranici

			return "create";
		}

	}

	@RequestMapping(value = "/link/{customUrl}", method = RequestMethod.GET)
	private String handleAnonmyousUserLinkViewGet(@PathVariable String customUrl, Model model) {

		LOGGER.debug("Handle anonymous user link view get controller invoked.");

		try {
			Link link = linkService.findAnonmyousUserLink(customUrl);

			return "redirect:" + link.getOriginalUrl();
		} catch (MyException e) {
			LOGGER.error("Exception occured, see following stack trace for more details.", e);

			return "home"; // TODO: error page
		}

	}

	@RequestMapping(value = "/viewLink/{username}/{customUrl}", method = RequestMethod.GET)
	public String handleRegisteredUserLinkViewGet(@PathVariable String username, @PathVariable String customUrl,
			Model model,
			HttpSession session) {

		LOGGER.debug("Handle user link view get controller invoked.");

		User sessionUser = (User) session.getAttribute("user");

		try {
			Link link = linkService.findLinkByCreatedByAndCustomUrl(username, customUrl, sessionUser);

			model.addAttribute("viewedLink", new ViewLinkDto(link));

			// TODO: provera da li je link javno vidljiv, ili da li se email od ulogovanog korisnik nalazi na listi
			// korisnika kojima je dozvoljen pregled linka
			/*
			 * if(createdBy != null) { if(createdBy.equals(link.getCreatedBy())) {
			 * 
			 * } }
			 */

			return "viewLink";
		} catch (MyException e) {
			LOGGER.error("Exception occured, see following stack trace for more details.", e);

			return "home";
		}

	}

	@RequestMapping(value = "/viewLink/anonymous/{customUrl}", method = RequestMethod.GET)
	public String handleAnonymousUserUploadedLinkViewGet(@PathVariable String customUrl, Model model) {

		// TODO: kako se anonymous nalazi u url, on ne može biti username od novoregistrovanog korisnika

		LOGGER.info("Handle anonymous user uploaded link view get controller invoked");

		try {
			Link link = linkService.findAnonmyousUserLink(customUrl);

			model.addAttribute("viewedLink", new ViewLinkDto(link));

			return "viewLink";

		} catch (MyException e) {
			LOGGER.error("Exception occured, see following stack trace for more details.", e);

			return "home";
		}

	}

	@RequestMapping(value = "/{username}/{customUrl}", method = RequestMethod.GET)
	public String handleLinkGet(@PathVariable String username, @PathVariable String customUrl) {

		LOGGER.debug("Handle link view get controler invoked");

		// TODO: ispitati da li je username ili customUrl null, i da li trebaju te provere i kako će se ponašati

		try {
			Link link = linkService.findLinkByUsernameAndCustomUrl(username, customUrl);

			LOGGER.debug("Link found: " + link);
			LOGGER.info("Redirecting to link: " + link.getOriginalUrl());

			return "redirect:" + link.getOriginalUrl();
		} catch (MyException e) {
			LOGGER.error("Exception occured, see following stack trace for more details.", e);

			return "home";
		}

	}

	@RequestMapping(value = "/edit/${customUrl}")
	public String handleLinkEditGet(@PathVariable String customUrl) {
		return "";
	}

	public String handleLinkEditPost() {
		return "";
	}

	public String handleLinkDeleteGet() {
		return "";
	}

}
